package com.itlong.cloud.operate.service.impl;

import com.itlong.cloud.POJO.DTO.operate.OperateFunctionGetPageDTO;
import com.itlong.cloud.POJO.PO.OperateFunctionPO;
import com.itlong.cloud.POJO.PO.OperateUserInfoPO;
import com.itlong.cloud.POJO.VO.operate.OperateAllotFunctionGetVO;
import com.itlong.cloud.POJO.VO.operate.OperateAssessFunctionVO;
import com.itlong.cloud.POJO.VO.operate.OperateFunctionVO;
import com.itlong.cloud.POJO.VO.operate.OperateGetRoleMenuVO;
import com.itlong.cloud.PlatformConstants;
import com.itlong.cloud.constants.RedisConstant;
import com.itlong.cloud.enumerate.DataStatusEnum;
import com.itlong.cloud.enumerate.OperateSystemSetUpEnum;
import com.itlong.cloud.operate.dao.IOperateAssessFunctionDao;
import com.itlong.cloud.operate.dao.IOperateFunctionDao;
import com.itlong.cloud.operate.service.IOperateFunctionService;
import com.itlong.cloud.operate.service.IOperateUserInfoService;
import com.itlong.cloud.service.RedisService;
import com.itlong.cloud.utils.data.handler.SqlUtil;
import com.itlong.cloud.utils.node.JsonUtil;
import com.itlong.cloud.utils.page.Page;
import com.itlong.cloud.utils.random.LogicIdUtil;
import com.itlong.cloud.utils.words.StringHandlerUtil;
import org.slf4j.Logger;import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * <desc>
 *      运营-菜单资源业务处理接口实现类
 * </desc>
 *
 * @createDate 2017/09/21
 */
@Service
public class OperateFunctionServiceImpl implements IOperateFunctionService{
    private static final Logger LOG = LoggerFactory.getLogger(OperateGroupServiceImpl.class);
    @Autowired
    IOperateFunctionDao iOperateFunctionDao;

    @Autowired
    RedisService<OperateFunctionPO> redisService;

    @Autowired
    IOperateUserInfoService iOperateUserInfoService;

    @Autowired
    private IOperateAssessFunctionDao iOperateAssessFunctionDao;

    /**
     * <desc>
     *      保存资源
     * </desc>
     *
     * @param operateFunctionPO 资源实体
     * @return  sql执行行数
     * @author Jiaqi.X
     * @createDate 2017/09/14
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer save(OperateFunctionPO operateFunctionPO) throws Exception {
        operateFunctionPO.setFunctionId(LogicIdUtil.bussinessId());
        operateFunctionPO.setCreateTime(new Date());
        operateFunctionPO.setStatus(DataStatusEnum.NORMAL.getType());
        if(operateFunctionPO.getParent().equals("0")){
            if(operateFunctionPO.getFunctionUrl().equals("")){
                operateFunctionPO.setFunctionUrl("/");
            }
            if(operateFunctionPO.getIdentifier().equals("")){
                operateFunctionPO.setIdentifier("home");
            }
        }
        return iOperateFunctionDao.save(SqlUtil.durableData(operateFunctionPO, PlatformConstants.TABLE_SAVE));
    }


    /**
     * <desc>
     *      更新资源
     * </desc>
     *
     * @param operateFunctionPO 资源实体
     * @return sql执行行数
     * @author Jiaqi.X
     * @createDate 2017/09/14
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer update(OperateFunctionPO operateFunctionPO) throws Exception {
        operateFunctionPO.setUpdateTime(new Date());
        return iOperateFunctionDao.update(SqlUtil.durableData(operateFunctionPO,PlatformConstants.TABLE_UPDATE));
    }

    /**
     * <desc>
     *      通过id获取资源
     * </desc>
     *
     * @param operateFunctionPO 资源实体
     * @return 资源实体
     * @author Jiaqi.X
     * @createDate 2017/09/14
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public OperateFunctionPO getOne(OperateFunctionPO operateFunctionPO) {
        return iOperateFunctionDao.getOne(operateFunctionPO);
    }

    /**
     * <desc>
     *      获取所有资源
     * </desc>
     *
     * @return 资源结果集
     * @author Jiaqi.X
     * @createDate 2017/09/14
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<OperateFunctionPO> getList() {
        return iOperateFunctionDao.getList();
    }

    /**
     * <desc>
     *      获取分页数据
     * </desc>
     *
     * @param pageDTO 查询参数DTO
     * @return page模型
     * @author Jiaqi.X
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public Page<OperateFunctionPO> getPage(OperateFunctionGetPageDTO pageDTO) throws Exception {
        //将DTO转换为Map params
        Map<String, Object> params = SqlUtil.convertBeanToMapParams(pageDTO);
        //分页类默认pageSize为20
        Page<OperateFunctionPO> page = new Page<>();
        page.getPage().setPageSize(pageDTO.getPageSize());
        page.getPage().setCurrentPage(pageDTO.getCurrentPage());
        params.put("currentPage",page.getPage().getStartSlip());
        params.put("pageSize",page.getPage().getPageSize());
        //填充返回数据集
        page.setRows(iOperateFunctionDao.getPage(params), iOperateFunctionDao.getPageCount(params));
        return page;
    }

    /**
     * <desc>
     *      删除资源
     * </desc>
     *
     * @param functionIds 资源id数组
     * @return sql执行行数
     * @author Jiaqi.X
     * @createDate 2017/09/21
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public Integer delete(String functionIds) {
        String functionId[] = StringHandlerUtil.splitString(functionIds);
        return iOperateFunctionDao.delete(functionId,new Date());
    }

    /**
     * <desc>
     *      获取下级集合
     * </desc>
     * @param functionId 资源id
     * @return 子级结果集
     * @author Jiaqi.X
     * @createDate 2017/9/21
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<OperateFunctionVO> getChilds(String functionId) {
        List<OperateFunctionVO> roots=iOperateFunctionDao.getChildsByParent(functionId,1);
        roots.forEach(child->{
            List<OperateFunctionVO> list = iOperateFunctionDao.getChildsByParent(child.getFunctionId(),1);
            if(list != null && !list.isEmpty()){
                child.setHaveChild("true");
            }
        });
        return roots;
    }

    /**
     * <desc>
     *      获取分配菜单所有节点
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/26
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<OperateAllotFunctionGetVO> getAllotFunction(String roleId){
        //运营菜单
        List<OperateFunctionVO> roots = iOperateFunctionDao.getChildsByParent("0",2);
        List<String> roleFunctions = iOperateFunctionDao.getRoleFunctions(roleId);
        roots = recursionFunction(roots,roleFunctions);
        //报价系统菜单
        List<OperateAssessFunctionVO> assessFunctionVOS = iOperateAssessFunctionDao.getChild("0",2);
        List<String> assessRoleFunctions = iOperateAssessFunctionDao.getRoleFunctions(roleId);
        assessFunctionVOS = recursionAssessFunction(assessFunctionVOS,assessRoleFunctions);
        //组装返回数据
        OperateAllotFunctionGetVO<OperateFunctionVO> operateFunctionGetVO = new OperateAllotFunctionGetVO();
        List<OperateAllotFunctionGetVO> operateAllotFunctionGetVOS = new ArrayList<>();
        operateFunctionGetVO.setSystemName("运营系统");
        operateFunctionGetVO.setFunctionList(roots);
        operateAllotFunctionGetVOS.add(operateFunctionGetVO);
        OperateAllotFunctionGetVO<OperateAssessFunctionVO> assessFunctionGetVOS = new OperateAllotFunctionGetVO();
        assessFunctionGetVOS.setSystemName("报价系统");
        assessFunctionGetVOS.setFunctionList(assessFunctionVOS);
        operateAllotFunctionGetVOS.add(assessFunctionGetVOS);
        return operateAllotFunctionGetVOS;
    }

    /**
     * <desc>
     *      获取当前节点的父级节点以及同级别所有父级节点
     * </desc>
     *
     * @param parent 资源id
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/30
     */
    @Override
    public List<OperateFunctionPO> getParentLevelFunctions(String parent) {
        OperateFunctionPO operateFunctionPO=iOperateFunctionDao.getParent(parent);
        try {
            List<OperateFunctionPO> parents = iOperateFunctionDao.getParentLevelFunctions(operateFunctionPO.getParent());
            return parents;
        }catch (Exception e){
            return null;
        }
    }

    /**
     * <desc>
     *      获取用户角色的菜单
     * </desc>
     *
     * @param roleIds 角色id
     * @return
     * @author Jiaqi.X
     * @cerateDate 2017/10/17
     */
    @Override
    public List<OperateGetRoleMenuVO> getRoleMenu(String roleIds) {
        String[] roles=StringHandlerUtil.splitString(roleIds);
        //检查用户是否是系统管理员
        boolean isAdmin=false;
        //屏蔽工程人员的角色
        List<String> roleList=new ArrayList<>();
        for(String rId : roles){
            if(!rId.equals("1")){
                roleList.add(rId);
            }
            if(rId.equals(OperateSystemSetUpEnum.ADMIN.getType().toString())){
                isAdmin=true;
            }
        }
        roles=roleList.toArray(new String[roleList.size()]);
        List<OperateGetRoleMenuVO> list=new ArrayList<>();
        //获取一级
        List<OperateFunctionVO> menus;
        if(isAdmin){
            menus=iOperateFunctionDao.getChildsByParent("0",2);
        }else{
            menus=iOperateFunctionDao.getFunctionByRoleId(roles,"0");
        }
        //遍历获取二级
        for(OperateFunctionVO menu:menus){
            OperateGetRoleMenuVO vo=new OperateGetRoleMenuVO();
            vo.setFunctionId(menu.getFunctionId());
            vo.setPath(menu.getFunctionUrl().equals("") ? "/" : menu.getFunctionUrl());
            vo.setComponent(menu.getIdentifier().equals("") ? "home" : menu.getIdentifier());
            vo.setName(menu.getFunctionName());
            vo.setIconCls(menu.getIcon());
            vo.setHidden("false");
            if(isAdmin) {
                menu.setChilds(iOperateFunctionDao.getChildsByParent(menu.getFunctionId(),2));
            }else{
                menu.setChilds(iOperateFunctionDao.getFunctionByRoleId(roles, menu.getFunctionId()));
            }

            if(menu.getChilds() != null && !menu.getChilds().isEmpty()){
                vo.setLeaf("true");
                List<OperateGetRoleMenuVO> childList=new ArrayList<>();
                for(OperateFunctionVO childMenu:menu.getChilds()){
                    OperateGetRoleMenuVO childVo=new OperateGetRoleMenuVO();
                    childVo.setFunctionId(childMenu.getFunctionId());
                    childVo.setPath(childMenu.getFunctionUrl());
                    childVo.setComponent(childMenu.getIdentifier());
                    childVo.setName(childMenu.getFunctionName());
                    childVo.setIconCls(childMenu.getIcon());
                    childVo.setHidden("false");
                    //为二级菜单填充权限
                    List<OperateFunctionVO> qxs;
                    if(isAdmin) {
                        qxs = iOperateFunctionDao.getChildsByParent(childMenu.getFunctionId(),2);
                    }else{
                        qxs = iOperateFunctionDao.getFunctionByRoleId(roles, childMenu.getFunctionId());
                    }
                    if(qxs.size()>0){
                        childVo.setLeaf("true");
                    }else{
                        childVo.setLeaf("false");
                    }
                    List<OperateGetRoleMenuVO> qxMenu=new ArrayList<>();
                    qxs.forEach(qx->{
                        OperateGetRoleMenuVO qxm=new OperateGetRoleMenuVO();
                        qxm.setFunctionId(qx.getFunctionId());
                        qxm.setPath(qx.getFunctionUrl());
                        qxm.setComponent(qx.getIdentifier());
                        qxm.setName(qx.getFunctionName());
                        qxm.setIconCls(qx.getIcon());
                        qxm.setLeaf("false");
                        qxm.setHidden("true");
                        qxMenu.add(qxm);
                    });
                    childVo.setChildren(qxMenu);
                    childList.add(childVo);
                }
                vo.setChildren(childList);
            }else{
                vo.setLeaf("false");
            }

            list.add(vo);
        }
        return list;
    }

    /**
     * <desc>
     *      获取用户角色的按钮权限
     * </desc>
     *
     * @param roleIds 角色id 多个,号分隔
     * @param functionId    当前点击菜单id
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/17
     */
    @Override
    public List<OperateGetRoleMenuVO> getAuthBtns(String roleIds, String functionId) {
        String[] roles=StringHandlerUtil.splitString(roleIds);
        //检查用户是否是系统管理员
        boolean isAdmin=false;
        //屏蔽工程人员的角色
        List<String> roleList=new ArrayList<>();
        for(String rId : roles){
            if(!rId.equals("1")){
                roleList.add(rId);
            }
            if(rId.equals(OperateSystemSetUpEnum.ADMIN.getType().toString())){
                isAdmin=true;
            }
        }
        roles=roleList.toArray(new String[roleList.size()]);
        List<OperateFunctionVO> menus;
        List<OperateGetRoleMenuVO> list=new ArrayList<>();
        if(isAdmin){
            menus = iOperateFunctionDao.getChildsByParent(functionId,2);
        }else{
            menus = iOperateFunctionDao.getFunctionByRoleId(roles,functionId);
        }
        for(OperateFunctionVO menu:menus) {
            OperateGetRoleMenuVO vo = new OperateGetRoleMenuVO();
            vo.setPath(menu.getFunctionUrl());
            vo.setComponent(menu.getIdentifier());
            vo.setName(menu.getFunctionName());
            vo.setIconCls(menu.getIcon());
            vo.setHidden("true");
            vo.setLeaf("false");
            list.add(vo);
        }
        return list;
    }

    /**
     * <desc>
     *      获取角色权限的所有资源并缓存至redis
     * </desc>
     *
     * @param roleIds 角色id 多个,号分隔
     * @return
     * @author Jiaqi.X
     * @createDate 2017/10/17
     */
    @Override
    public List<OperateFunctionPO> getRoleAuthFunctions(String roleIds,String token) throws IOException {
        OperateUserInfoPO userInfo=iOperateUserInfoService.retrieve(token);
        String funstr=redisService.get(RedisConstant.OPERATE_REDIS_USER_AUTH_KEY + userInfo.getUserId());
        List<OperateFunctionPO> list;
        if(funstr==null) {
            String[] roles = StringHandlerUtil.splitString(roleIds);
            //屏蔽工程人员的角色
            List<String> roleList=new ArrayList<>();
            for(String rId : roles){
                if(!rId.equals("1")){
                    roleList.add(rId);
                }
            }
            roles=roleList.toArray(new String[roleList.size()]);
            //判断是否是管理员
            for (String role : roles) {
                if (role.equals(OperateSystemSetUpEnum.ADMIN.getType().toString())) {
                    roles = null;
                    break;
                }
            }
            list=iOperateFunctionDao.getRoleAuthFunctions(roles);
            list.forEach(function->{
                function=(OperateFunctionPO)StringHandlerUtil.formatString(function);
            });
            //添加进缓存
            redisService.set(RedisConstant.OPERATE_REDIS_USER_AUTH_KEY + userInfo.getUserId(),RedisConstant.OPERATE_LOGIN_TIME,JsonUtil.toJSON(list));
        }else{
            list= JsonUtil.toObject(redisService.get(RedisConstant.OPERATE_REDIS_USER_AUTH_KEY + userInfo.getUserId()),List.class);
        }
        return list;
    }

    /**
     * <desc>
     *      递归获取所有节点 并查询角色是否已有该节点
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/26
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<OperateFunctionVO> recursionFunction(List<OperateFunctionVO> roots,List<String> roleFunctions){
        roots.forEach(child->{
            List<OperateFunctionVO> list = iOperateFunctionDao.getChildsByParent(child.getFunctionId(),2);
            //遍历roleFunctions查找第一个与child functionId相同的值，将child的haveAuth设为true
            if(roleFunctions.stream().filter(rf ->
                            rf.equals(child.getFunctionId())
                            ).findFirst().isPresent()){
                child.setHaveAuth("true");
            }
            if(list != null && !list.isEmpty()){
                //遍历菜单节点与角色菜单判断是否已有
                list.forEach(function->{
                    if(roleFunctions.stream().filter(rf ->
                                    rf.equals(function.getFunctionId())
                                    ).findFirst().isPresent()){
                        function.setHaveAuth("true");
                    }
                });
                child.setHaveChild("true");
                child.setChilds(this.recursionFunction(list,roleFunctions));
            }
        });
        return roots;
    }

    /**
     * <desc>
     *      递归获取所有报价菜单 并查询角色是否已有该菜单
     * </desc>
     *
     * @return
     * @author Jiaqi.X
     * @createDate 2017/09/26
     */
    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public List<OperateAssessFunctionVO> recursionAssessFunction(List<OperateAssessFunctionVO> roots,List<String> roleFunctions){
        roots.forEach(child->{
            List<OperateAssessFunctionVO> list = iOperateAssessFunctionDao.getChild(child.getFunctionId(),2);
            //遍历roleFunctions查找第一个与child functionId相同的值，将child的haveAuth设为true
            if(roleFunctions.stream().filter(rf ->
                    rf.equals(child.getFunctionId())
            ).findFirst().isPresent()){
                child.setHaveAuth("true");
            }
            if(list != null && !list.isEmpty()){
                //遍历菜单节点与角色菜单判断是否已有
                list.forEach(function->{
                    if(roleFunctions.stream().filter(rf ->
                            rf.equals(function.getFunctionId())
                    ).findFirst().isPresent()){
                        function.setHaveAuth("true");
                    }
                });
                child.setHaveChild("true");
                child.setChilds(this.recursionAssessFunction(list,roleFunctions));
            }
        });
        return roots;
    }





}
